﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Globalization;

namespace SharePointOfView.Diagnostics
{
    /// <summary>
    /// SharePointOfView Logger
    /// </summary>
    public sealed class SPLog
    {
        #region Static statements

        private static volatile SPLog instance;
        private static object syncRoot = new Object();
        private static MethodInfo logMethod;

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        private SPLog() 
        {
            Assembly ass = Assembly.Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
            System.Type[] types = ass.GetTypes();

            // On récupere le type qui nous intéresse 
            Type ULSType = Type.GetType("Microsoft.SharePoint.Diagnostics.ULS, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
            logMethod = ULSType.GetMethods(BindingFlags.Static | BindingFlags.Public)[19];
        }

        #endregion

        #region Instance

        /// <summary>
        /// Singleton accessor to the SPLog class
        /// </summary>
        public static SPLog Instance
        {
            get
            {
                if(instance == null)
                {
                    lock(syncRoot)
                    {
                        if(instance == null)
                        {
                            instance = new SPLog();
                        }
                    }
                }
                return instance;
            }
        }

        #endregion

        #region Log Methods

        /// <summary>
        /// Log the specified string within the SharePoint ULS
        /// </summary>
        /// <param name="format">String to log</param>
        /// <param name="args">Array of arguments if any, null otherwise.</param>
        /// <remarks>Used TraceLevel will be TraceLevel.High</remarks>
        public static void LogString(string format, params object[] args)
        {
            LogString(format, ULSTraceLevel.High, args);
        }

        /// <summary>
        /// Log the specified string within the SharePoint ULS
        /// </summary>
        /// <param name="format">String to log</param>
        /// <remarks>Used TraceLevel will be TraceLevel.High</remarks>
        public static void LogString(string format)
        {
            LogString(format, ULSTraceLevel.High, null);
        }

        /// <summary>
        /// Log the specified string within the SharePoint ULS
        /// </summary>
        /// <param name="format">String to log</param>
        /// <param name="TraceLevel">Trace level associate to the string to log.</param>
        /// <param name="args">Array of arguments if any, null otherwise.</param>
        public static void LogString(string format, ULSTraceLevel TraceLevel, params object[] args)
        {
            try
            {
                if (SPLog.Instance != null)
                {
                    string str;
                    if (args != null)
                    {
                        str = string.Format(CultureInfo.InvariantCulture, format, args);
                    }
                    else
                    {
                        str = format;
                    }
                    logMethod.Invoke(null, new object[] { ULSTagID.tag_81vt, ULSCat.msoulscat_OSRV_General, TraceLevel, "%s", new object[] { str } });
                }
            }
            catch
            {
                // Logger should not throw exception
            }
        }

        #endregion
    }
}
